//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//********************************************************* 

using Microsoft.TridentWordAddIn.Common;
using System.Collections.Generic;
using System;
using System.Threading;
using System.Linq;
using System.Windows.Forms;
using Microsoft.TridentWordAddIn.ResourceHelper;

namespace Microsoft.TridentWordAddIn.Presentation
{
    internal partial class InsertResultIntoDocumentForm : BaseForm
    {
        string fileName = string.Empty;
        private WorkflowAssociation association;
        private Thread downloadThread;
        public List<JobOutput> Outputs { get; private set; }
        private OutputType outputType;
        private bool isOrginal;
        private IController controllerInstance;
        int documentKey;

        /// <summary>
        /// Initializes a new instance of the <see cref="InsertResultIntoDocumentForm"/> class.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="outputType">Type of the output.</param>
        /// <param name="isOrginal">if set to <c>true</c> [is orginal].</param>
        /// <param name="association">The association.</param>
        public InsertResultIntoDocumentForm(string fileName, OutputType outputType, bool isOrginal, WorkflowAssociation association)
        {        
            this.InitializeComponent();

            this.fileName = fileName;
            this.outputType = outputType;
            this.isOrginal = isOrginal;
            this.association = association;
            Outputs = new JobOutputCollection();
            lblSelectedResultFile.Text = "Selected Result File : " + fileName;
            this.controllerInstance = Controller.Instance(null);
            this.documentKey = this.controllerInstance.CurrentDocumentKey;
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="InsertResultIntoDocumentForm"/> is failed.
        /// </summary>
        /// <value><c>true</c> if failed; otherwise, <c>false</c>.</value>
        public bool Failed { get; set; }

        /// <summary>
        /// Gets the comment.
        /// </summary>
        /// <value>The comment.</value>
        public string Comment
        {
            get
            {
                return this.txtComment.Text;
            }
        }

        /// <summary>
        /// Gets a value indicating whether [insert single result].
        /// </summary>
        /// <value><c>true</c> if [insert single result]; otherwise, <c>false</c>.</value>
        public bool SingleResult
        {
            get
            {
                return this.rbnSelectedFile.Checked;
            }
        }

        /// <summary>
        /// Gets a value indicating whether [insert input parameter details].
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [insert input parameter details]; otherwise, <c>false</c>.
        /// </value>
        public bool InsertParameters
        {
            get
            {
                return this.chkInsertInputParameterDetails.Checked;
            }
        }

        /// <summary>
        /// Downloads the job outputs.
        /// </summary>
        private void DownloadJobOutputs()
        {
            if (!this.isOrginal)
            {
                ITridentServer rerunServer = Controller.Instance(null).ServerBroker.GetVerifiedServer(association.RerunJob.Connection);
                if (rerunServer != null)
                {
                    if (rbnAllResultFiles.Checked)
                    {
                        this.Outputs = rerunServer.GetJobOutputs(association.RerunJob.JobId);
                        bool isFinal = (outputType == OutputType.Workflow ? true : false);
                        var outputs = from output in this.Outputs
                                      where output.IsDataProduct == isFinal
                                      select output;
                        this.Outputs = outputs.ToList<JobOutput>();
                    }
                    else
                    {
                        foreach (ShallowJobOutput jobOutput in association.RerunJob.Job.Outputs)
                        {
                            if (this.fileName == jobOutput.Name)
                            {
                                this.Outputs.Add(rerunServer.GetJobOutputById(jobOutput.Id));
                                return;
                            }
                        }
                    }

                    rerunServer.Dispose();
                }
                else
                {
                    this.Failed = true;
                    MessageBoxHelper.ShowDefault(ResourceFetcher.GetString("InvalidRerunConnection"), MessageBoxIcon.Error);
                }
            }
            else
            {
                Model model = this.controllerInstance.GetModelByDocumentKey(this.documentKey);
                foreach (ShallowJobOutput result in association.Job.Outputs)
                {
                    Guid fileId = model.Modules[result.Id].File.Guid;
                    if (!rbnAllResultFiles.Checked)
                    {
                        if (result.Name.Compare(this.fileName))
                        {
                            this.Outputs.Add(CreateJobOutPut(fileId, result));
                            break;
                        }
                        continue;
                    }

                    bool isFinal = (outputType == OutputType.Workflow ? true : false);
                    if (result.IsDataProduct == isFinal)
                    {
                        this.Outputs.Add(CreateJobOutPut(fileId, result));
                    }
                }
            }
        }

        /// <summary>
        /// Creates the job out put.
        /// </summary>
        /// <param name="fileId">The file id.</param>
        /// <param name="shallowJobOutput">The shallow job output.</param>
        /// <returns></returns>
        JobOutput CreateJobOutPut(Guid fileId, ShallowJobOutput shallowJobOutput)
        {
            byte[] resultData = this.controllerInstance.DataStore.GetFileData(this.documentKey, fileId);
            string fileName = shallowJobOutput.Name + shallowJobOutput.Extension;
            return new JobOutput(shallowJobOutput.Id, fileName, resultData, shallowJobOutput.IsDataProduct);
                            
        }
        /// <summary>
        /// Handles the Click event of the btnOK control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnOK_Click(object sender, System.EventArgs e)
        {
            this.downloadThread = new Thread(new ThreadStart(DownloadJobOutputs));
            this.btnOK.Enabled = false;
            this.downloadThread.Start();
            this.downloadTimer.Start();
            this.downloadProgressBar.Visible = true;
            this.lblDownloadStatus.Visible = true;
        }

        /// <summary>
        /// Handles the Click event of the btnCancel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            downloadThread.CancelThread();
        }

        /// <summary>
        /// Handles the Tick event of the downloadTimer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void downloadTimer_Tick(object sender, EventArgs e)
        {
            if (!downloadThread.IsAlive)
            {
                this.downloadTimer.Stop();
                if (this.Failed)
                {
                    this.downloadTimer.Stop();
                    this.downloadProgressBar.Visible = false;
                    this.lblDownloadStatus.Visible = false;
                    this.btnOK.Enabled = true;
                }
                else
                {
                    DialogResult = System.Windows.Forms.DialogResult.OK;
                }
            }
        }
    }
}